package com.yanqu.road.server.channelserver.manager.activity.pasture;

import com.yanqu.road.dao.impl.activity.pasture.channel.ChannelPastureUserDataDaoImpl;
import com.yanqu.road.entity.activity.ActivityInfo;
import com.yanqu.road.entity.activity.entername.ActivityGroupMatch;
import com.yanqu.road.entity.activity.entername.ChannelFightZone;
import com.yanqu.road.entity.activity.entername.UserEnterName;
import com.yanqu.road.entity.activity.entername.compare.ChannelEnterNameGroupRankSort;
import com.yanqu.road.entity.activity.entername.compare.ChannelEnterNameUserRankSort;
import com.yanqu.road.entity.activity.pasture.channel.ChannelPastureUserData;
import com.yanqu.road.entity.enums.eGamePlayerEventType;
import com.yanqu.road.entity.player.UserBaseInfo;
import com.yanqu.road.logic.pb.PlayerBasePb;
import com.yanqu.road.pb.cross3.activity.EnterNameProto;
import com.yanqu.road.pb.cross3.activity.XRankProto;
import com.yanqu.road.server.channelserver.manager.activity.ChannelActivityInfoMgr;
import com.yanqu.road.server.channelserver.manager.activity.entername.*;
import com.yanqu.road.server.channelserver.manager.activity.entername.rank.EnterNameGroupRank;
import com.yanqu.road.server.channelserver.manager.activity.entername.rank.EnterNameMyRankData;
import com.yanqu.road.server.channelserver.manager.activity.entername.rank.EnterNameRank;
import com.yanqu.road.server.channelserver.manager.activity.entername.rank.EnterNameRankModel;

import java.math.BigInteger;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;

public class ChannelPastureActivity extends TempEnterNameActivity implements EnterNameActivity {

    private ActivityInfo activityInfo;

    private final Object addLock = new Object();

    //userId
    private Map<Long, ChannelPastureUserData> userDataMap;

    public ChannelPastureActivity(ActivityInfo activityInfo) {
        super(activityInfo);
        this.activityInfo = activityInfo;
        setAllAreaRank(false);
    }

    public boolean loadData(){
        //加载数据
        userDataMap = new ChannelPastureUserDataDaoImpl().getChannelPastureUserData(activityInfo.getActivityId());
        return true;
    }

    /**
     * 在业务数据及报名数据加载后，初始化
     */
    public void initDataRank() {
        //个人榜单（单局最高积分）
        int rankMax = ChannelActivityInfoMgr.getChannelActivityMaxRank(activityInfo.getActivityId(), eGamePlayerEventType.ChannelPastureMaxScoreRank.getValue());
        //榜单按分组，有多个的
        //key是matchGroupId
        Map<Integer, EnterNameRankModel> matchRankModelMap = new ConcurrentHashMap<>();

        //按地区汇总
        Map<Integer, List<ChannelPastureUserData>> zoneUserMap = new HashMap<>();

        //按分配的阵营初始化
        EnterNameModel nameModel = ChannelEnterNameMgr.getEnterNameModel(getActivityInfo().getActivityId());
        if(nameModel != null){
            for (Map.Entry<Long, ChannelPastureUserData> dataEntry : userDataMap.entrySet()) {
                ChannelPastureUserData data = dataEntry.getValue();
                UserEnterName userEnterName = nameModel.getUserEnterName(data.getUserId());
                if(userEnterName == null){
                    continue;
                }
                if(!zoneUserMap.containsKey(userEnterName.getZoneId())){
                    zoneUserMap.put(userEnterName.getZoneId(), new LinkedList<>());
                }
                zoneUserMap.get(userEnterName.getZoneId()).add(data);
            }
            Map<Integer, ActivityGroupMatch> matchMap = nameModel.getMatchMap();

            //分组个人
            for (Map.Entry<Integer, ActivityGroupMatch> matchEntry : matchMap.entrySet()) {
                ActivityGroupMatch groupMatch = matchEntry.getValue();
                int matchGroupId = groupMatch.getRankMatchGroupId();
                if(matchRankModelMap.containsKey(matchGroupId)){
                    continue;
                }
                EnterNameRankModel userRankModel = new EnterNameRankModel(getActivityInfo().getActivityId(), eGamePlayerEventType.ChannelPastureMaxScoreRank.getValue(), matchGroupId, rankMax);

                List<Integer> zoneIdList = getMatchGroupZoneList(matchMap, groupMatch);

                LinkedList<ChannelPastureUserData> list = new LinkedList<>();
                for (Integer zoneId : zoneIdList) {
                    if(zoneUserMap.containsKey(zoneId)){
                        list.addAll(zoneUserMap.get(zoneId));
                    }
                }

                setUserModelData(rankMax, userRankModel, list);
                matchRankModelMap.put(matchGroupId, userRankModel);
            }

            //地区个人前50
            for (ChannelFightZone zone : nameModel.getZoneList()) {
                if(!zoneUserMap.containsKey(zone.getAreaId())){
                    continue;
                }
                EnterNameRankModel userRankModel = new EnterNameRankModel(getActivityInfo().getActivityId(), eGamePlayerEventType.ChannelPastureMaxScoreRank.getValue(), zone.getAreaId(), 50);
                LinkedList<ChannelPastureUserData> list = new LinkedList<>();
                list.addAll(zoneUserMap.get(zone.getAreaId()));
                setUserModelData(rankMax, userRankModel, list);
                matchRankModelMap.put(zone.getAreaId(), userRankModel);
            }
        }
        if(matchRankModelMap.size() > 0){
            ChannelEnterNameRankMgr.initRank(getActivityInfo().getActivityId(), eGamePlayerEventType.ChannelPastureMaxScoreRank.getValue(), matchRankModelMap);
        }

        //分组榜单
        initGroupRank(nameModel, zoneUserMap);
    }

    private void setUserModelData(int rankMax, EnterNameRankModel userRankModel, LinkedList<ChannelPastureUserData> list) {
        //排序，进行冲榜
        list.sort(new ChannelEnterNameUserRankSort());
        int size = list.size();
        LinkedList<EnterNameRank> rankList = new LinkedList<>();
        for (int i = 0; i < size && i < rankMax; i++) {
            ChannelPastureUserData userData = list.get(i);
            if(userData.getUserBaseInfo() == null){
                continue;
            }
            EnterNameRank nameRank = getEnterNameRank(userData);
            rankList.add(nameRank);
        }
        userRankModel.setRankList(rankList);
    }

    private EnterNameRank getEnterNameRank(ChannelPastureUserData userData) {
        EnterNameRank nameRank = new EnterNameRank();
        nameRank.setUserId(userData.getUserId());
        nameRank.setChannelId(userData.getChannelId());
        nameRank.setGroupId(userData.getGroupId());
        nameRank.setZoneId(userData.getZoneId());
        nameRank.setValue(BigInteger.valueOf(userData.getUserRankValue()));//最高伤害
        nameRank.setLastUpdateTime(userData.getLastUpdateTime() / 1000);
        nameRank.setUserBaseInfo(userData.getUserBaseInfo());
        nameRank.setParam("");
        return nameRank;
    }

    private void initGroupRank(EnterNameModel nameModel, Map<Integer, List<ChannelPastureUserData>> zoneUserMap) {
        if(nameModel == null){
            return;
        }
        //按分配的阵营初始化
        Map<Integer, BigInteger> groupValueMap = new HashMap<>();
        Map<Integer, Long> groupUpdateTimeMap = new HashMap<>();
        //按分配的阵营初始化数据
        for (Map.Entry<Integer, ActivityGroupMatch> matchEntry : nameModel.getMatchMap().entrySet()) {
            ActivityGroupMatch groupMatch = matchEntry.getValue();
            LinkedList<ChannelPastureUserData> list = new LinkedList<>();
            for (Integer zoneId : groupMatch.getZoneIdList()) {
                if(zoneUserMap.containsKey(zoneId)){
                    list.addAll(zoneUserMap.get(zoneId));
                }
            }
            for (ChannelPastureUserData userData : list) {
                if (userData.getBadge() <= 0) {
                    continue;
                }
                BigInteger val = groupValueMap.getOrDefault(groupMatch.getGroupId(), BigInteger.ZERO);
                groupValueMap.put(groupMatch.getGroupId(), val.add(BigInteger.valueOf(userData.getBadge())));
                long updateTime = groupUpdateTimeMap.getOrDefault(groupMatch.getGroupId(), 0L);
                if (updateTime < userData.getLastUpdateTime2()) {
                    groupUpdateTimeMap.put(groupMatch.getGroupId(), userData.getLastUpdateTime2());
                }
            }
        }
        initGroupRankModel(nameModel.getMatchMap(), groupValueMap, groupUpdateTimeMap);
    }

    /**
     * 玩家数据初始化，由区服变更触发（报名时候，并没有初始化）
     * @param userBaseInfo  首次变更一定要有赋值 定时更新
     */
    public ChannelPastureUserData getChannelPastureUserData(long userId, UserBaseInfo userBaseInfo){
        ChannelPastureUserData userData = userDataMap.get(userId);
        if(userData != null){
            if(userBaseInfo != null){
                userData.setUserBaseInfo(userBaseInfo);
            }
            return userData;
        }
        synchronized (addLock){
            userData = userDataMap.get(userId);
            if(userData == null){
                userData = new ChannelPastureUserData();
                userData.setActivityId(activityInfo.getActivityId());
                userData.setUserId(userId);
                if(userBaseInfo != null) {
                    userData.setUserBaseInfo(userBaseInfo);
                }
                userData.setInsertOption();
                userDataMap.put(userId, userData);
            }
        }
        //拿分组
        UserEnterName userEnterName = ChannelEnterNameMgr.getUserEnterName(activityInfo.getActivityId(), userId);
        if(userEnterName != null){
            userData.setChannelId(userEnterName.getChannelId());
            userData.setGroupId(userEnterName.getGroupId());
            userData.setZoneId(userEnterName.getZoneId());
            if(userBaseInfo == null){
                userData.setUserBaseInfo(userEnterName.getUserBaseInfo());
            }else {
                userEnterName.setUserBaseInfo(userBaseInfo);
            }
        }
        return userData;
    }

    public void save(){
        if(userDataMap != null){
            for (Map.Entry<Long, ChannelPastureUserData> entry : userDataMap.entrySet()) {
                ChannelPastureUserData userData = entry.getValue();
                if(userData.isInsertOption()){
                    new ChannelPastureUserDataDaoImpl().add(userData);
                }else if(userData.isUpdateOption()){
                    new ChannelPastureUserDataDaoImpl().update(userData);
                }
            }
        }
    }

    @Override
    public void changeUserValue(long userId, int type, BigInteger value, String param, UserBaseInfo userBaseInfo) {
        ChannelPastureUserData userData = getChannelPastureUserData(userId, userBaseInfo);
        synchronized (userData) {
            if (type == eGamePlayerEventType.ChannelPastureMaxScoreRank.getValue()) {
                if (value.longValue() < userData.getScore()) {
                    //没有超过最高分数
                    return;
                }
                userData.setScore(value.longValue());
                userData.setRound(Integer.valueOf(param));
                userData.setLastUpdateTime(System.currentTimeMillis());
            } else if (type == eGamePlayerEventType.EnterNameAreaFightRank.getValue()) {
                if (value.longValue() <= userData.getBadge()) {
                    return;
                }
                userData.setBadge(value.longValue());
                userData.setLastUpdateTime2(System.currentTimeMillis());
            }
        }

        ActivityGroupMatch match = ChannelEnterNameMgr.getActivityGroupMatch(activityInfo.getActivityId(), userId);
        if(match == null) {
            return;
        }

        if(type == eGamePlayerEventType.ChannelPastureMaxScoreRank.getValue()){
            EnterNameRank rank = new EnterNameRank();
            rank.setUserId(userId);
            rank.setGroupId(userData.getGroupId());
            rank.setConditionType(type);
            rank.setLastUpdateTime(System.currentTimeMillis() / 1000);
            rank.setValue(value);
            rank.setParam("");
            rank.setZoneId(userData.getZoneId());
            rank.setUserBaseInfo(userData.getUserBaseInfo());
            ChannelEnterNameRankMgr.changeUserRank(activityInfo.getActivityId(), type, match.getRankMatchGroupId(), rank);
        }

        //统计分组数据
        if(type == eGamePlayerEventType.EnterNameAreaFightRank.getValue()){
            UserEnterName userEnterName = ChannelEnterNameMgr.getUserEnterName(activityInfo.getActivityId(), userId);
            if(userEnterName != null && userEnterName.getGroupId() > 0){
                BigInteger total = BigInteger.ZERO;
                for (Map.Entry<Long, ChannelPastureUserData> entry : userDataMap.entrySet()) {
                    ChannelPastureUserData member = entry.getValue();
                    if(member.getGroupId() == userEnterName.getGroupId()){
                        total = total.add(BigInteger.valueOf(member.getGroupRankValue()));
                    }
                }
                EnterNameGroupRank groupRank = new EnterNameGroupRank();
                groupRank.setType(type);
                groupRank.setGroupId(match.getGroupId());
                groupRank.setValue(total);
                groupRank.setLastUpdateTime(userData.getLastUpdateTime2() / 1000);
                ChannelEnterNameRankMgr.changeGroupValue(activityInfo.getActivityId(), eGamePlayerEventType.EnterNameAreaFightRank.getValue(), match.getRankMatchGroupId(), groupRank);
            }
        }
    }

    /**
     * top 50的玩家
     * @param userData
     */
    public XRankProto.XUserRankMsg.Builder getUserBuilder(ChannelPastureUserData userData) {
        XRankProto.XUserRankMsg.Builder builder = XRankProto.XUserRankMsg.newBuilder();
        builder.setUserId(userData.getUserId());
        builder.setChannelId(userData.getChannelId());
        builder.setValue(String.valueOf(userData.getScore()));
        builder.setParam(String.valueOf(userData.getBadge()));  //这边是勋章
        builder.setExtendParam("");
        builder.setUpdateTime(userData.getLastUpdateTime() / 1000);
        builder.setBaseInfo(PlayerBasePb.parsePlayerBaseTempMsg(userData.getUserBaseInfo()));
        return builder;
    }

    /**
     * 勋章贡献
     */
    public XRankProto.XUserRankMsg.Builder getUserGroupBuilder(ChannelPastureUserData userData) {
        XRankProto.XUserRankMsg.Builder builder = XRankProto.XUserRankMsg.newBuilder();
        builder.setUserId(userData.getUserId());
        builder.setChannelId(userData.getChannelId());
        builder.setValue(String.valueOf(userData.getBadge()));
        builder.setParam(String.valueOf(userData.getScore()));   //也要显示单局最高
        builder.setUpdateTime(userData.getLastUpdateTime2() / 1000);
        builder.setBaseInfo(PlayerBasePb.parsePlayerBaseTempMsg(userData.getUserBaseInfo()));
        return builder;
    }

    @Override
    public EnterNameProto.EnterNameGroupMemberListMsg.Builder getGroupMember(int page, int pageSize, int groupId, int type) {
        EnterNameProto.EnterNameGroupMemberListMsg.Builder msg = EnterNameProto.EnterNameGroupMemberListMsg.newBuilder();
        msg.setPage(page);
        List<ChannelPastureUserData> list = getUserDataByGroupId(groupId);
        list.sort(new ChannelEnterNameGroupRankSort());
        int start = (page - 1) * pageSize;
        int end = page * pageSize;
        int size = list.size();
        for (int i = start; i < size && i < end; i++) {
            ChannelPastureUserData userData = list.get(i);
            XRankProto.XUserRankMsg.Builder builder;
            if(userData.getUserBaseInfo() == null){
                continue;
            }
            if(type == eGamePlayerEventType.EnterNameAreaFightRank.getValue()){
                builder = getUserGroupBuilder(userData);
            }else {
                builder = getUserBuilder(userData);
            }
            msg.addRank(builder);
        }
        return msg;
    }

    @Override
    public EnterNameMyRankData getMyRankData(int type, UserEnterName name) {
        EnterNameMyRankData rankData = new EnterNameMyRankData();
        //个人榜单才需要业务数据吧，分组的直接拿榜单
        ChannelPastureUserData userData = userDataMap.get(name.getUserId());
        if(userData != null){
            rankData.setValue(String.valueOf(userData.getScore()));
            rankData.setParam("");
        }
        return rankData;
    }

    public List<ChannelPastureUserData> getUserDataByGroupId(int groupId) {
        List<ChannelPastureUserData> list = new LinkedList<>();
        for (Map.Entry<Long, ChannelPastureUserData> dataEntry : userDataMap.entrySet()) {
            ChannelPastureUserData data = dataEntry.getValue();
            if (data.getGroupId() == groupId) {
                list.add(data);
            }
        }
        return list;
    }

    public ActivityInfo getActivityInfo() {
        return activityInfo;
    }

    @Override
    public int getGroupConditionType() {
        return eGamePlayerEventType.EnterNameAreaFightRank.getValue();
    }

    @Override
    public int getUserConditionType() {
        return eGamePlayerEventType.ChannelPastureMaxScoreRank.getValue();
    }
}
